﻿//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
// Exo² ffa01
// Copyright (C) 2007-2008 Samuel Lacroix and Raphaël Legouge
//
// Distributed under GNU General Public License
// See the License folder of Exo² for details
//
//
// http://www.codeplex.com/exo2 (eng)
//-----------------------------------------------------------------------------


#include "stdafx.h"
#pragma hdrstop
#include "ffa 01.h"

#include "gui.h"
#include "serverpacket.h"

                        
CFFA FFA;


CFFA::CFFA()                 
{
        this->pDev              = NULL;
        this->DXUTExtensions    = false;
        DXUTSetCursorSettings(true, true); 
}                                     


void CFFA::RegisterGameActions()                      
{         

}
                    

void CFFA::DeviceCreated()
{
        this->pDev = Exo2::CRenderer::Instance().GetD3DDevice();/*
        if (!this->pCam)
            this->pCam.reset(new Exo2::CCameraFPSFly);
        this->pCam->Move(0, 0, 0);
        Exo2::CRenderer::Instance().SetCamera(this->pCam);*/      
}

                                              
void CFFA::DeviceDestroyed()
{
        this->pDev = NULL;   
}                                        


void CFFA::DeviceReset() 
{
        Exo2::CRenderer::Instance().EnableLighting(true);
        Exo2::CRenderer::Instance().EnableSpecularLighting(true);
}
                            

void CFFA::DeviceLost()                 
{  
                     
}                                      


void CFFA::RegisterConfigProperties()
{                                      
        CApplication::RegisterConfigProperties();
}


void CFFA::OnCreated()         
{
    // Menu
        // Manager d'options
        this->pMenuDataManager.reset(new GUI::CMenuDataManager);
        
        // Chemins du menu
        const tstring MenuFileName = _T("data/menu/menu.xml");
        const tstring StateSpriteFileName = _T("data/menu/statesprites.xml");
        
        // Enregistrement des composants
        GUI::RegisterComponents();
        
        // Enregistrement des composants dans la console
#ifdef _DEBUG
        Exo2::CMenuManager::Instance().RegisterComponentPropertiesInConsole = true;
#else
        Exo2::CMenuManager::Instance().RegisterComponentPropertiesInConsole = false;
#endif
        
        // Chargement des states sprites
        GUI::CButton::SetStateSpriteFileName(StateSpriteFileName);
        GUI::CTextButton::SetStateSpriteFileName(StateSpriteFileName);
        GUI::CCheckBox::SetStateSpriteFileName(StateSpriteFileName);
        GUI::CHorizontalSlider::SetStateSpriteFileName(StateSpriteFileName);
        GUI::CVerticalSlider::SetStateSpriteFileName(StateSpriteFileName);
                                                                                             
        // Evenements du menu
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonprofil"),                          GUI::OnClickTextButtonProfil,                               this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonhost"),                            GUI::OnClickTextButtonHost,                                 this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonjoin"),                            GUI::OnClickTextButtonJoin,                                 this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonoptions"),                         GUI::OnClickTextButtonOptions,                              this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttoncredits"),                         GUI::OnClickTextButtonCredits,                              this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonexit"),                            GUI::OnClickTextButtonExit,                                 this);
        // Menu Options
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonoptionsapply"),                    GUI::OnClickTextButtonOptionsApply,                         this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonoptionscancel"),                   GUI::OnClickTextButtonOptionsCancel,                        this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonoptionsdefaults"),                 GUI::OnClickTextButtonOptionsDefaults,                      this);
        // Menu Options/Graphics
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonoptionsgraphicsresolutionprev"),   GUI::OnClickTextButtonOptionsGraphicsResolutionPrev,        this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonoptionsgraphicsresolutionnext"),   GUI::OnClickTextButtonOptionsGraphicsResolutionNext,        this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclickcheckboxoptionsgraphicssyncvert"),           GUI::OnClickCheckBoxOptionsGraphicsSyncVert,                this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclickcheckboxoptionsgraphicswindowed"),           GUI::OnClickCheckBoxOptionsGraphicsWindowed,                this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonoptionsgraphicsfiltrationprev"),   GUI::OnClickTextButtonOptionsGraphicsFiltrationPrev,        this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonoptionsgraphicsfiltrationnext"),   GUI::OnClickTextButtonOptionsGraphicsFiltrationNext,        this);
        // Menu Options/Audio
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonoptionsaudiodeviceprev"),          GUI::OnClickTextButtonOptionsAudioDevicePrev,               this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonoptionsaudiodevicenext"),          GUI::OnClickTextButtonOptionsAudioDeviceNext,               this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onchangeslideroptionsaudiomaster"),                 GUI::OnChangeSliderOptionsAudioMaster,                      this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onchangeslideroptionsaudiomusic"),                  GUI::OnChangeSliderOptionsAudioMusic,                       this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onchangeslideroptionsaudioeffects"),                GUI::OnChangeSliderOptionsAudioEffects,                     this);
        // Menu Options/Physics
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onchangeslideroptionsphysicsaccuracy"),             GUI::OnChangeSliderOptionsPhysicsAccuracy,                  this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onchangeslideroptionsphysicsparticlelimitation"),   GUI::OnChangeSliderOptionsPhysicsParticleLimitation,        this);
        // Menu Host
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonhostcreate"),                      GUI::OnClickTextButtonHostCreate,                           this);
        // Menu Join
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonjoinjoingame"),                    GUI::OnClickTextButtonJoinJoinGame,                         this);
        // Menu exit
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonexityes"),                         GUI::OnClickTextButtonExitYes,                              this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonexitno"),                          GUI::OnClickTextButtonExitNo,                               this);
        // Menu Profil
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonprofilplayershipprev"),            GUI::OnClickTextButtonProfilPlayerShipPrev,                 this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonprofilplayershipnext"),            GUI::OnClickTextButtonProfilPlayerShipNext,                 this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onchangesliderprofilactionscroll"),                 GUI::OnChangeSliderProfilActionScroll,                      this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onenterlabelprofilaction"),                         GUI::OnEnterLabelProfilAction,                              this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onleavelabelprofilaction"),                         GUI::OnLeaveLabelProfilAction,                              this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicklabelprofilaction0"),                        GUI::OnClickLabelProfilAction0,                             this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicklabelprofilaction1"),                        GUI::OnClickLabelProfilAction1,                             this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicklabelprofilaction2"),                        GUI::OnClickLabelProfilAction2,                             this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicklabelprofilaction3"),                        GUI::OnClickLabelProfilAction3,                             this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicklabelprofilaction4"),                        GUI::OnClickLabelProfilAction4,                             this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicklabelprofilaction5"),                        GUI::OnClickLabelProfilAction5,                             this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicklabelprofilaction6"),                        GUI::OnClickLabelProfilAction6,                             this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicklabelprofilaction7"),                        GUI::OnClickLabelProfilAction7,                             this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicklabelprofilaction8"),                        GUI::OnClickLabelProfilAction8,                             this);
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicklabelprofilaction9"),                        GUI::OnClickLabelProfilAction9,                             this);
        // Menu Loading
        Exo2::CMenuManager::Instance().RegisterMenuEvent(   _T("onclicktextbuttonloadingcancel"),                   GUI::OnClickTextButtonLoadingCancel,                        this);
                                                             
        // Chargement du menu
        Exo2::CMenuManager::Instance().Load(MenuFileName);
        
        // Données utilisées dans les menus
        boost::shared_ptr<GUI::IMenuData> pMenuData; 
        
        // Menu "profil"
        pMenuData.reset(new GUI::CMenuDataProfil(this));
        this->pMenuDataManager->SetData(pMenuData, _T("profil")); 
        
        // Menu "host"
        pMenuData.reset(new GUI::CMenuDataHost(this));
        this->pMenuDataManager->SetData(pMenuData, _T("host"));
        
        // Menu "join"
        pMenuData.reset(new GUI::CMenuDataJoin(this));
        this->pMenuDataManager->SetData(pMenuData, _T("join"));
                
        // Menu "options"
        pMenuData.reset(new GUI::CMenuDataOptions(this));
        this->pMenuDataManager->SetData(pMenuData, _T("options"));
        
        // Menu "credits"
        pMenuData.reset(new GUI::CMenuDataCredits(this));
        this->pMenuDataManager->SetData(pMenuData, _T("credits"));
        
        // Menu "exit"
        pMenuData.reset(new GUI::CMenuDataExit(this));
        this->pMenuDataManager->SetData(pMenuData, _T("exit"));
        
        // On met à jour les menus
        this->pMenuDataManager->LoadDataFromApplication(_T("profil"));
        this->pMenuDataManager->UpdateComponentFromData(_T("profil"));        
        this->pMenuDataManager->LoadDataFromApplication(_T("host"));
        this->pMenuDataManager->UpdateComponentFromData(_T("host"));  
        this->pMenuDataManager->LoadDataFromApplication(_T("join"));
        this->pMenuDataManager->UpdateComponentFromData(_T("join"));
        this->pMenuDataManager->LoadDataFromApplication(_T("options"));
        this->pMenuDataManager->UpdateComponentFromData(_T("options"));
        this->pMenuDataManager->LoadDataFromApplication(_T("credits"));
        this->pMenuDataManager->UpdateComponentFromData(_T("credits"));
        this->pMenuDataManager->LoadDataFromApplication(_T("exit"));
        this->pMenuDataManager->UpdateComponentFromData(_T("exit"));
        
        // Création de l'objet qui va redimensionner le menu lors des changements de résolution
        this->pMenuDynamicResize.reset(new GUI::COnResolutionChange(this->pMenuDataManager.get()));
        this->pMenuDynamicResize->OnNewResolution();
        
        shared_ptr<Exo2::CShellCommand> pCommand;
        
        #define ADD_COMMAND(Name, Usage, Description, Function)\
        pCommand.reset(new Exo2::CShellCommand(Name, Usage, Description, boost::bind(&Function, boost::ref(*this), _1), Exo2::CShell::EndUserScope));\
        Shell().RegisterCommand(pCommand)
        
    // Server
        ADD_COMMAND(_T("sv_create"),                    _T("sv_create port [maxplayers=32 [password=\"\"]]"),           _T("Create a server with the given specifications"),            CFFA::ServerCreateCmd);
        ADD_COMMAND(_T("sv_destroy"),                   _T("sv_destroy"),                                               _T("Destroy the created server"),                               CFFA::ServerDestroyCmd);
        ADD_COMMAND(_T("sv_kick"),                      _T("sv_kick {playername|playerid}"),                            _T("Disconnect the selected peer"),                             CFFA::ServerKickCmd);
        ADD_COMMAND(_T("sv_ban"),                       _T("sv_ban  {ipaddress|playername|playerid} [kick=1]"),         _T("Ban the selected player or ban IP"),                        CFFA::ServerBanCmd);
        ADD_COMMAND(_T("sv_unban"),                     _T("sv_unban ipaddress"),                                       _T("Unban the selected ip address"),                            CFFA::ServerUnbanCmd);
        ADD_COMMAND(_T("sv_getbanned"),                 _T("sv_getbanned"),                                             _T("Return the ip address black-list"),                         CFFA::ServerGetBannedCmd);
        ADD_COMMAND(_T("sv_getpeersinfo"),              _T("sv_getpeersinfo"),                                          _T("Return informations about peers"),                          CFFA::ServerGetPeersInfoCmd);
        ADD_COMMAND(_T("sv_tickrate"),                  _T("sv_tickrate [rate]"),                                       _T("Get or set the server tickrate"),                           CFFA::ServerTickRateCmd);
        ADD_COMMAND(_T("sv_welcomemessage"),            _T("sv_welcomemessage [message]"),                              _T("Get or set the welcome message"),                           CFFA::ServerWelcomMessageCmd);
        ADD_COMMAND(_T("sv_verbosity"),                 _T("sv_verbosity [value]"),                                     _T("Get or set the verbosity of the server"),                   CFFA::ServerVerbosityCmd);
        ADD_COMMAND(_T("sv_getplayersinfo"),            _T("sv_getplayersinfo"),                                        _T("Return informations about players"),                        CFFA::ServerGetPlayersInfoCmd);
        ADD_COMMAND(_T("sv_say"),                       _T("sv_say message"),                                           _T("Send a message to all players"),                            CFFA::ServerSayCmd);

    // Client
        ADD_COMMAND(_T("cl_create"),                    _T("cl_create [tickrate=60 [maxdownloadrate=0 maxuploadrate=0]]"),      _T("Create a client with the given specifications"),                    CFFA::ClientCreateCmd);
        ADD_COMMAND(_T("cl_destroy"),                   _T("cl_destroy"),                                                       _T("Destroy the created client"),                                       CFFA::ClientDestroyCmd);
        ADD_COMMAND(_T("cl_tickrate"),                  _T("cl_tickrate [rate]"),                                               _T("Get or set the client tickrate"),                                   CFFA::ClientTickRateCmd);
        ADD_COMMAND(_T("cl_verbosity"),                 _T("cl_verbosity [value]"),                                             _T("Get or set the verbosity of the client"),                           CFFA::ClientVerbosityCmd);
        ADD_COMMAND(_T("cl_join"),                      _T("cl_join host port name [password=\"\"]"),                           _T("Connect to the server and join"),                                   CFFA::ClientJoinCmd);
        ADD_COMMAND(_T("cl_quit"),                      _T("cl_quit"),                                                          _T("Exit the game and disconnect from the server"),                     CFFA::ClientQuitCmd);
        ADD_COMMAND(_T("cl_name"),                      _T("cl_name [name]"),                                                   _T("Get the current name or ask the server for a new one"),             CFFA::ClientNameCmd);
        ADD_COMMAND(_T("cl_updaterate"),                _T("cl_updaterate [rate]"),                                             _T("Get the current update rate or ask the server for a new one"),      CFFA::ClientUpdateRateCmd);
        ADD_COMMAND(_T("cl_interpolation"),             _T("cl_interpolation [interpolation]"),                                 _T("Get the current interpolation or ask the server for a new one"),    CFFA::ClientInterpolationCmd);
        ADD_COMMAND(_T("cl_netgraph"),                  _T("cl_netgraph"),                                                      _T("Return the netgraph result"),                                       CFFA::ClientNetgraphCmd);
        ADD_COMMAND(_T("cl_say"),                       _T("cl_say message"),                                                   _T("Send a message to all players"),                                    CFFA::ClientSayCmd);
        ADD_COMMAND(_T("cl_latencies"),                 _T("cl_latencies [inlatency outlatency]"),                              _T("Get or set in/out latencies"),                                      CFFA::ClientLatenciesCmd);
        ADD_COMMAND(_T("cl_loss"),                      _T("cl_loss [inprobability outprobability]"),                           _T("Get or set in/out loss"),                                           CFFA::ClientLossCmd);
        ADD_COMMAND(_T("cl_getplayersinfo"),            _T("cl_getplayersinfo"),                                                _T("Return informations about players"),                                CFFA::ClientGetPlayersInfoCmd);
        
        #undef ADD_COMMAND
        
        this->pNetService.reset(new Exo2::CNetService);
}
                                

void CFFA::OnDestroying()                       
{
        this->pMenuDynamicResize.reset();
        Exo2::CMenuManager::Destroy();
        
        this->pServer.reset();
        this->pClient.reset();
        this->pNetService.reset();
}                        
                                                    

void CFFA::Update(double TotalTime, float ElapsedTime)
{
    // Menu
        // Mise à jour du menu
        UpdateMenu(TotalTime, ElapsedTime);
        
    // Network
        this->pNetService->Update();
        if (this->pServer)
            this->pServer->Update(TotalTime, ElapsedTime);
        if (this->pClient)
            this->pClient->Update(TotalTime, ElapsedTime);
}


void CFFA::UpdateMenu(double TotalTime, float ElapsedTime)
{
        Exo2::CMenuManager::Instance().Update(ElapsedTime, TotalTime);
}                       
                      

void CFFA::Render3D() const
{
        EXO_DXTIF(this->pDev->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xFF000000, 1.f, 0));        
        
    #ifdef USE_RBS
        Exo2::CRenderBatchingSystem::Instance().Render();
    #else

    #endif
}                       
                                                       
                        
void CFFA::Render2D() const
{ 
        Exo2::CMenuManager::Instance().Render2D();
}


bool CFFA::ServerCreateCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("sv_create"));
        
        try
        {
                if (this->pServer)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le serveur est déjà créé"));
                        return true;
                }
                unsigned short Port = 0;
                tstring Password = _T("");
                size_t MaxPlayers = 32;
                switch (Instructions.size())
                {
                    case 4:
                        Password = Instructions[3];
                    case 3:
                        MaxPlayers = Exo2::Utils::StringToValue<size_t>(Instructions[2]);
                    case 2:
                        Port = Exo2::Utils::StringToValue<unsigned short>(Instructions[1]);
                        this->pServer.reset(new CServer(Port, MaxPlayers, Password));
                        this->pNetService->Register(*this->pServer);
                        return true;
                    default:
                        return false;
                }
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ServerDestroyCmd(const std::vector<tstring> &Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("sv_destroy"));
        
        try
        {
                if (!this->pServer)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le serveur n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        this->pNetService->Unregister(*this->pServer);
                        this->pServer.reset();
                        Exo2::CLogger::Instance().Log(_T("*** Serveur détruit"));
                        return true;
                }
                else
                    return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ClientCreateCmd( const std::vector<tstring>& Instructions )
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("cl_create"));

        try
        {
                if (this->pClient)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le client est déjà créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        this->pClient.reset(new CClient);
                        this->pNetService->Register(*this->pClient);
                        Exo2::CLogger::Instance().Log(_T("*** Client créé"));
                        return true;
                }
                else
                {
                        return false;
                }
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ClientDestroyCmd( const std::vector<tstring>& Instructions )
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("cl_destroy"));

        try
        {
                if (!this->pClient)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le client n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        this->pNetService->Unregister(*this->pClient);
                        this->pClient.reset();
                        Exo2::CLogger::Instance().Log(_T("*** Client détruit"));
                        return true;
                }
                else
                        return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ServerKickCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("sv_kick"));

        try
        {
                if (!this->pServer)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le serveur n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 2)
                {
                        // Il faut déterminer si on nous envoie un PlayerID ou un nom de joueur
                        if (Instructions[1].find_first_not_of(_T("1234567890")) == tstring::npos)
                        {       // Il n'y a que des chiffres => PlayerID (le serveur n'autorise pas un nom de player comportant que des chiffres)
                                this->pServer->KickPlayer(Exo2::Utils::StringToValue<size_t>(Instructions[1]));
                        }
                        else
                        {
                                this->pServer->KickPlayer(Instructions[1]);
                        }
                        return true;                        
                }
                else
                    return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ServerBanCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("sv_ban"));

        try
        {
                if (!this->pServer)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le serveur n'est pas créé"));
                        return true;
                }
                bool KickAfterban = true;
                switch (Instructions.size())
                {
                    case 3:     //sv_ban PlayerID/PlayerName KickAfterBan
                        KickAfterban = Exo2::Utils::StringToValue<bool>(Instructions[2]);
                    case 2:
                        // On regarde si c'est le PlayerID ou bien si c'est le nom
                        if (Instructions[1].find_first_not_of(_T("1234567890")) == tstring::npos)
                        {       // Il n'y a que des chiffres => PlayerID (le serveur n'autorise pas un nom de player comportant que des chiffres)
                                this->pServer->BanPlayer(Exo2::Utils::StringToValue<size_t>(Instructions[1]), KickAfterban);
                        }
                        else if (Exo2::CNetUtils::IsIpAddress(Instructions[1]))  // C'est une adresse IP on ban l'adresse, mais on ne fait rien d'autre
                        {
                                this->pServer->Ban(Instructions[1], false);
                        }
                        else
                        {
                                this->pServer->BanPlayer(Instructions[1], KickAfterban);
                        }
                        return true;
                    default:
                        return false;                        
                }
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ServerUnbanCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("sv_unban"));

        try
        {
                if (!this->pServer)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le serveur n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 2)
                {
                        this->pServer->Unban(Instructions[1]);
                        return true;
                }
                return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ServerGetBannedCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("sv_getbanned"));

        try
        {
                if (!this->pServer)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le serveur n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        const Exo2::INetServer::TIpAddresses& IPs = this->pServer->GetBannedIpAddresses();
                        if (IPs.empty())
                            Exo2::CLogger::Instance().Log(_T("No IP address banned"));
                        else
                        {
                                for (Exo2::INetServer::TIpAddresses::const_iterator pIP = IPs.begin(); pIP != IPs.end(); ++pIP)
                                {
                                        Exo2::CLogger::Instance().Log(*pIP);
                                }

                        }
                        return true;
                }
                return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
} 


bool CFFA::ServerGetPeersInfoCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("sv_getpeersinfo"));

        try
        {
                if (!this->pServer)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le serveur n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        size_t PeerNumber = 0;
                        const Exo2::CSlot<Exo2::CNetPeer>::TSlots& Peers = this->pServer->GetPeers();
                        tostringstream oss;
                        for (size_t i = 0; i < Peers.size(); ++i)
                        {
                                if (Peers[i])
                                {
                                        ++PeerNumber;
                                        Exo2::CNetPeer& Peer = *Peers[i];
                                        oss.str(_T(""));
                                        oss <<  i << _T(" : ") << Peer.GetIpAddress();
                                        switch (Peer.ConnectionState)
                                        {
                                            case Exo2::CS_NOT_CONNECTED:
                                                oss << _T("  not connected ");
                                                break;
                                            case Exo2::CS_CONNECTING:
                                                oss << _T("  connecting");
                                                break;
                                            case Exo2::CS_CONNECTED:
                                                oss << _T("  connected");
                                                break;
                                            case Exo2::CS_DISCONNECTING:
                                                oss << _T("  disconnecting");
                                        }
                                        Exo2::CLogger::Instance().Log(oss.str());
                                }
                        }
                        if (PeerNumber == 0)
                            Exo2::CLogger::Instance().Log(_T("No peer connected"));
                        return true;
                }
                return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}   


bool CFFA::ServerTickRateCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("sv_tickrate"));

        try
        {
                if (!this->pServer)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le serveur n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        tostringstream oss;
                        oss << this->pServer->GetTickRate();
                        Exo2::CLogger::Instance().Log(oss.str());
                        return true;
                }
                else if (Instructions.size() == 2)
                {
                        double Rate = Exo2::Utils::StringToValue<double>(Instructions[1]);
                        this->pServer->SetTickRate(Rate);
                        std::vector<tstring> Strings;
                        Strings.push_back(_T("sv_tickrate"));
                        Strings.push_back(Exo2::Utils::ValueToString(Rate));
                        Exo2::CLogger::Instance().Log(Exo2::Strings(Exo2::STR_ARG1_SET_TO_ARG2, Strings.begin(), Strings.end()));
                        return true;
                }
                return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
} 


bool CFFA::ServerWelcomMessageCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("sv_welcomemessage"));

        try
        {
                if (!this->pServer)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le serveur n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        Exo2::CLogger::Instance().Log(this->pServer->GetWelcomeMessage());
                        return true;
                }
                else if (Instructions.size() == 2)
                {
                        tstring Message = Instructions[1];
                        this->pServer->SetWelcomeMessage(Message);
                        std::vector<tstring> Strings;
                        Strings.push_back(_T("sv_welcomemessage"));
                        Strings.push_back(Message);
                        Exo2::CLogger::Instance().Log(Exo2::Strings(Exo2::STR_ARG1_SET_TO_ARG2, Strings.begin(), Strings.end()));
                        return true;
                }
                return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ClientTickRateCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("cl_tickrate"));

        try
        {
                if (!this->pClient)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le client n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        tostringstream oss;
                        oss << this->pClient->GetTickRate();
                        Exo2::CLogger::Instance().Log(oss.str());
                        return true;
                }
                else if (Instructions.size() == 2)
                {
                        double Rate = Exo2::Utils::StringToValue<double>(Instructions[1]);
                        this->pClient->SetTickRate(Rate);
                        std::vector<tstring> Strings;
                        Strings.push_back(_T("cl_tickrate"));
                        Strings.push_back(Exo2::Utils::ValueToString(Rate));
                        Exo2::CLogger::Instance().Log(Exo2::Strings(Exo2::STR_ARG1_SET_TO_ARG2, Strings.begin(), Strings.end()));
                        return true;
                }
                return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ServerVerbosityCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("sv_verbosity"));

        try
        {
                if (!this->pServer)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le serveur n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        tostringstream oss;
                        oss << this->pServer->GetVerbosity();
                        Exo2::CLogger::Instance().Log(oss.str());
                        return true;
                }
                else if (Instructions.size() == 2)
                {
                        size_t Value = Exo2::Utils::StringToValue<size_t>(Instructions[1]);
                        this->pServer->SetVerbosity(Value);
                        std::vector<tstring> Strings;
                        Strings.push_back(_T("sv_verbosity"));
                        Strings.push_back(Exo2::Utils::ValueToString(Value));
                        Exo2::CLogger::Instance().Log(Exo2::Strings(Exo2::STR_ARG1_SET_TO_ARG2, Strings.begin(), Strings.end()));
                        return true;
                }
                return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ClientVerbosityCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("cl_verbosity"));

        try
        {
                if (!this->pClient)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le client n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        tostringstream oss;
                        oss << this->pClient->GetVerbosity();
                        Exo2::CLogger::Instance().Log(oss.str());
                        return true;
                }
                else if (Instructions.size() == 2)
                {
                        size_t Value = Exo2::Utils::StringToValue<size_t>(Instructions[1]);
                        this->pClient->SetVerbosity(Value);
                        std::vector<tstring> Strings;
                        Strings.push_back(_T("cl_verbosity"));
                        Strings.push_back(Exo2::Utils::ValueToString(Value));
                        Exo2::CLogger::Instance().Log(Exo2::Strings(Exo2::STR_ARG1_SET_TO_ARG2, Strings.begin(), Strings.end()));
                        return true;
                }
                return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ClientJoinCmd( const std::vector<tstring>& Instructions )
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("cl_join"));

        try
        {
                if (!this->pClient)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le client n'est pas créé"));
                        return true;
                }
                tstring Password = _T("");
                tstring Name = _T("");
                unsigned short Port = 0;
                tstring HostIpAddress;
                switch (Instructions.size())
                {
                    case 5:
                        Password = Instructions[4];
                    case 4:
                        Name = Instructions[3];
                    case 3:
                        Port = Exo2::Utils::StringToValue<unsigned short>(Instructions[2]);
                    case 2:
                        HostIpAddress = Instructions[1];
                        this->pClient->ConnectThenJoin(HostIpAddress, Port, Name, Password);
                        return true;                        
                default:
                        return false;                       
                }
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ServerGetPlayersInfoCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("sv_getplayersinfo"));

        try
        {
                if (!this->pServer)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le serveur n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        size_t PlayerNumber = 0;
                        for (size_t i = 0; i < this->pServer->GetPlayers().size(); ++i)
                        {
                                tostringstream oss;
                                const shared_ptr<CServerPlayer>& pPlayer = this->pServer->GetPlayers()[i];
                                if (pPlayer)
                                {
                                        ++PlayerNumber;
                                        oss << pPlayer->Name << _T(" :") << _T(" ping=") << size_t(pPlayer->Ping * 1000) << _T("ms updaterate=") << pPlayer->UpdateRate << _T("fps interp=") << size_t(pPlayer->Interpolation * 1000) << _T("ms state=");
                                        switch (pPlayer->State)
                                        {
                                            case CServerPlayer::PS_NOT_JOINNED:
                                                {
                                                        oss << Exo2::Strings(Exo2::STR_NOT_JOINNED);
                                                        break;
                                                }
                                            case CServerPlayer::PS_JOINNING:
                                                {
                                                        oss << Exo2::Strings(Exo2::STR_JOINNING);
                                                        break;
                                                }
                                            case CServerPlayer::PS_SYNCHRONIZING:
                                                {
                                                        oss << Exo2::Strings(Exo2::STR_SYNCHRONIZING);
                                                        break;
                                                }
                                            case CServerPlayer::PS_JOINNED:
                                                {
                                                        oss << Exo2::Strings(Exo2::STR_JOINNED) << _T(" (next synchro ") << int(1. / this->pServer->GetSynchronizationRate() - (this->pServer->GetTimeStamp() - pPlayer->LastSynchronizationEnd)) << _T("s)");
                                                        break;
                                                }
                                            case CServerPlayer::PS_RESYNCHRONIZING:
                                                {
                                                        oss << Exo2::Strings(Exo2::STR_RESYNCHRONIZING);
                                                        break;
                                                }
                                            default:
                                                {
                                                        oss << Exo2::Strings(Exo2::STR_UNKNONW_STATE);
                                                }
                                        }
                                        oss << _T(" playerID=") << i << _T(" peerID=") << pPlayer->PeerID;
                                        Exo2::CLogger::Instance().Log(oss.str());
                                }
                        }
                        if (PlayerNumber == 0)
                            Exo2::CLogger::Instance().Log(_T("No player in the game"));
                        return true;
                }
                else
                {
                        return false;
                }
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ClientNameCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("cl_name"));

        try
        {
                if (!this->pClient)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le client n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        tostringstream oss;
                        oss << this->pClient->GetName();
                        Exo2::CLogger::Instance().Log(oss.str());
                        return true;
                }
                else if (Instructions.size() == 2)
                {
                        this->pClient->SendChangeName(Instructions[1]);
                        tstring Args[2] = {_T("cl_name"), Instructions[1]};
                        Exo2::CLogger::Instance().Log(Exo2::Strings(Exo2::STR_REQUEST_SENT_TO_SET_ARG1_TO_ARG2, Args, Args + 2));
                        return true;
                }
                return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ClientUpdateRateCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("cl_updaterate"));

        try
        {
                if (!this->pClient)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le client n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        tostringstream oss;
                        oss << this->pClient->GetUpdateRate();
                        Exo2::CLogger::Instance().Log(oss.str());
                        return true;
                }
                else if (Instructions.size() == 2)
                {
                        size_t Value = Exo2::Utils::StringToValue<size_t>(Instructions[1]);
                        this->pClient->SendChangeUpdateRate(Value);
                        tstring Args[2] = {_T("cl_updaterate"), Exo2::Utils::ValueToString(Value)};
                        Exo2::CLogger::Instance().Log(Exo2::Strings(Exo2::STR_REQUEST_SENT_TO_SET_ARG1_TO_ARG2, Args, Args + 2));
                        return true;
                }
                return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ClientNetgraphCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("cl_netgraph"));

        try
        {
                if (!this->pClient)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le client n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        for (size_t i = 0; i < this->pClient->GetLastNetgraphResult().size(); ++i)
                        {
                                tostringstream oss;
                                switch (i)
                                { 
                                    case PACKET_SERVER_USAGE_LOCAL_PLAYER:
                                        oss << _T("local player : ");
                                        break;
                                    case PACKET_SERVER_USAGE_OTHER_PLAYER:
                                        oss << _T("other player : ");
                                        break;
                                    case PACKET_SERVER_USAGE_OTHER_ENTITIES:
                                        oss << _T("other entities : ");
                                        break;
                                    case PACKET_SERVER_USAGE_SOUNDS:
                                        oss << _T("sounds : ");
                                        break;
                                    case PACKET_SERVER_USAGE_TEMPORARY_ENTITIES:
                                        oss << _T("temporary entities : ");
                                        break;
                                    case PACKET_SERVER_USAGE_USER_MESSAGES:
                                        oss << _T("user messages : ");
                                        break;
                                    case PACKET_SERVER_USAGE_ENTITY_MESSAGES:
                                        oss << _T("entity messages : ");
                                        break;
                                    case PACKET_SERVER_USAGE_STRING_TABLE:
                                        oss << _T("string table : ");
                                        break;
                                    case PACKET_SERVER_USAGE_STRING_COMMANDS:
                                        oss << _T("string commands : ");
                                        break;
                                    case PACKET_SERVER_USAGE_PLAYER_VOICE:
                                        oss << _T("player voice : ");
                                }
                                oss << this->pClient->GetLastNetgraphResult()[i] << _T("o/s");
                                Exo2::CLogger::Instance().Log(oss.str());
                        }
                        return true;
                }
                return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ServerSayCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("sv_say"));

        try
        {
                if (!this->pServer)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le serveur n'est pas créé"));
                        return true;
                }
                if (Instructions.size() >= 2)
                {
                        tstring Message = _T("");
                        for (size_t i = 1; i < Instructions.size(); ++i)
                        {
                                Message += Instructions[i];
                                if (i != Instructions.size())
                                    Message += _T(" ");
                        }
                        this->pServer->Say(Message);
                        tostringstream oss;
                        oss << _T("admin says \"") << Message << _T("\"");
                        Exo2::CLogger::Instance().Log(oss.str());
                        return true;
                }
                return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ClientSayCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("cl_say"));

        try
        {
                if (!this->pClient)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le client n'est pas créé"));
                        return true;
                }
                if (Instructions.size() >= 2)
                {
                        tstring Message = _T("");
                        for (size_t i = 1; i < Instructions.size(); ++i)
                        {
                                Message += Instructions[i];
                                if (i != Instructions.size())
                                    Message += _T(" ");
                        }
                        this->pClient->Say(Message);
                        return true;
                }
                return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ClientLatenciesCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("cl_latencies"));

        try
        {
                if (!this->pClient)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le client n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        tostringstream oss;
                        oss << _T("in = ") << this->pClient->GetAdditionnalReceiveLatency();
                        Exo2::CLogger::Instance().Log(oss.str());
                        oss.str(_T(""));
                        oss << _T("out = ") << this->pClient->GetAdditionnalSendLatency();
                        Exo2::CLogger::Instance().Log(oss.str());
                        return true;
                }
                else if (Instructions.size() == 3)
                {
                        double In = Exo2::Utils::StringToValue<double>(Instructions[1]);
                        double Out = Exo2::Utils::StringToValue<double>(Instructions[2]);
                        this->pClient->SetAdditionnalSendLatency(Out);
                        this->pClient->SetAdditionnalReceiveLatency(In);
                        tstring Args[2] = {_T("in"), Exo2::Utils::ValueToString(this->pClient->GetAdditionnalReceiveLatency())};
                        Exo2::CLogger::Instance().Log(Exo2::Strings(Exo2::STR_ARG1_SET_TO_ARG2, Args, Args + 2));
                        tstring Args2[2] = {_T("out"), Exo2::Utils::ValueToString(this->pClient->GetAdditionnalSendLatency())};
                        Exo2::CLogger::Instance().Log(Exo2::Strings(Exo2::STR_ARG1_SET_TO_ARG2, Args2, Args2 + 2));
                        return true;
                }
                return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ClientLossCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("cl_loss"));

        try
        {
                if (!this->pClient)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le client n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        tostringstream oss;
                        oss << _T("in : ") << this->pClient->GetReceivePacketLossProbability();
                        Exo2::CLogger::Instance().Log(oss.str());
                        oss.str(_T(""));
                        oss << _T("out : ") << this->pClient->GetSentPacketLossProbability();
                        Exo2::CLogger::Instance().Log(oss.str());
                        return true;
                }
                else if (Instructions.size() == 3)
                {
                        double In = Exo2::Utils::StringToValue<double>(Instructions[1]);
                        double Out = Exo2::Utils::StringToValue<double>(Instructions[2]);
                        this->pClient->SetSentPacketLossProbability(Out);
                        this->pClient->SetReceivePacketLossProbability(In);
                        tstring Args[2] = {_T("in"), Exo2::Utils::ValueToString(this->pClient->GetReceivePacketLossProbability())};
                        Exo2::CLogger::Instance().Log(Exo2::Strings(Exo2::STR_ARG1_SET_TO_ARG2, Args, Args + 2));
                        tstring Args2[2] = {_T("out"), Exo2::Utils::ValueToString(this->pClient->GetSentPacketLossProbability())};
                        Exo2::CLogger::Instance().Log(Exo2::Strings(Exo2::STR_ARG1_SET_TO_ARG2, Args2, Args2 + 2));
                        return true;
                }
                return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ClientQuitCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("cl_quit"));

        try
        {
                if (!this->pClient)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le client n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        this->pClient->QuitThenDisconnect();
                        return true;
                }
                return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ClientInterpolationCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("cl_interpolation"));

        try
        {
                if (!this->pClient)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le client n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        tostringstream oss;
                        oss << _T("cl_interpolation ") << this->pClient->GetInterpolation();
                        Exo2::CLogger::Instance().Log(oss.str());
                        return true;
                }
                else if (Instructions.size() == 2)
                {
                        double Value = Exo2::Utils::StringToValue<double>(Instructions[1]);
                        this->pClient->SendChangeInterpolation(Value);
                        tstring Args[2] = {_T("cl_interpolation"), Exo2::Utils::ValueToString(Value)};
                        Exo2::CLogger::Instance().Log(Exo2::Strings(Exo2::STR_REQUEST_SENT_TO_SET_ARG1_TO_ARG2, Args, Args + 2));
                        return true;
                }
                return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}


bool CFFA::ClientGetPlayersInfoCmd(const std::vector<tstring>& Instructions)
{
        EXO_ASSERT(!Instructions.empty());
        EXO_ASSERT(Instructions[0] == _T("cl_getplayersinfo"));

        try
        {
                if (!this->pClient)
                {
                        Exo2::CLogger::Instance().Log(_T("*** Le client n'est pas créé"));
                        return true;
                }
                if (Instructions.size() == 1)
                {
                        size_t PlayerNumber = 0;
                        for (size_t i = 0; i < this->pClient->GetPlayers().size(); ++i)
                        {
                                const shared_ptr<CClientPlayer>& pPlayer = this->pClient->GetPlayers()[i];
                                if (pPlayer)
                                {
                                        ++PlayerNumber;
                                        tostringstream oss;
                                        oss << pPlayer->Name << _T(" : ping=") << pPlayer->Ping << _T("ms playerID=") << i;
                                        Exo2::CLogger::Instance().Log(oss.str());       
                                }
                        }
                        EXO_ASSERT(PlayerNumber != 0);
                        return true;
                }
                return false;
        }
        catch (Exo2::Exception& E)
        {
                Exo2::CLogger::Instance().Log(E.Message);
                return true;
        }
}